package com.xjscrm.server.service.common.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.xjscrm.common.entity.CorpApplication;
import com.xjscrm.common.entity.CorpApplicationDevice;
import com.xjscrm.common.entity.WwCorp;
import com.xjscrm.common.entity.WwDevice;
import com.xjscrm.common.enums.RedisCacheKeyEnum;
import com.xjscrm.common.utils.DateUtil;
import com.xjscrm.common.utils.ww.WwApiUtil;
import com.xjscrm.common.utils.ww.dto.UseridToOpenuseridResultDTO;
import com.xjscrm.common.utils.ww.dto.WwAppSecretResultDTO;
import com.xjscrm.common.utils.ww.dto.WwCustomerResultDTO;
import com.xjscrm.server.constant.Const;
import com.xjscrm.server.mapper.CorpApplicationDeviceMapper;
import com.xjscrm.server.mapper.CorpApplicationMapper;
import com.xjscrm.server.service.common.CorpApplicationService;
import com.xjscrm.server.service.device.WwDeviceService;
import com.xjscrm.server.service.qywxcallback.QywxCallbackService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.yaml.snakeyaml.events.Event;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @author liuqi
 * @date 2021年08月25日 20:17
 */
@Service
@Slf4j
public class CorpApplicationServiceImpl implements CorpApplicationService {

    @Autowired
    private CorpApplicationMapper corpApplicationMapper;
    @Autowired
    private CorpApplicationDeviceMapper corpApplicationDeviceMapper;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private QywxCallbackService qywxCallbackService;

    /**
     * 处理企业-是否关注企业应用
     *
     * @param
     * @return null
     * @author liuqi
     * @date 2021/8/13 11:38
     */
    @Async("taskExecutorForQywxCallback")
    public void handerCorpApplication(WwCorp wwCorp, WwDevice wwDevice) {

        if(wwCorp == null || wwDevice == null){
            return;
        }

        //限流key
        String rateLimitKey = "-handerCorpApplication-corpId-deviceUniqueId=" + wwCorp.getCorpId() + "_" + wwDevice.getId();
        Object object = redisTemplate.opsForValue().get(rateLimitKey);
        if (object == null) {
            redisTemplate.opsForValue().set(rateLimitKey, rateLimitKey, 300, TimeUnit.SECONDS);
        } else {
            return;
        }

        log.info("-----处理企业应用线程----corpId={},corpName={}", wwCorp.getCorpId(), wwCorp.getName());

        int now = DateUtil.getTime();

        try {
            //查询该企业，如果已经不存在，则添加
            CorpApplication corpApplication = corpApplicationMapper.selectByCorpId(wwCorp.getCorpId());
            if (corpApplication == null) {
                corpApplication = new CorpApplication();
                corpApplication.setId(IdWorker.getId());
                corpApplication.setMerId(wwCorp.getMerId());
                corpApplication.setCorpId(wwCorp.getCorpId());
                corpApplication.setCorpName(wwCorp.getName());
                corpApplication.setAuthCorpId(null);
                corpApplication.setPermanentCode(null);
                corpApplication.setCreateTime(now);
                corpApplication.setUpdateTime(now);
                corpApplicationMapper.insert(corpApplication);
            }

            //授权了应用，才会创建机器人
            if(StringUtils.isNotBlank(corpApplication.getAuthCorpId()) && StringUtils.isNotBlank(corpApplication.getPermanentCode())){

                //将机器人主体的userid转成服务商的openuserid
                List<String> userid_list = new ArrayList<>();
                userid_list.add(wwDevice.getAcctId());
                //获取此应用的授权
                String accessToken = WwApiUtil.getAppAccessToken(corpApplication.getAuthCorpId(), corpApplication.getPermanentCode());
                if(StringUtils.isBlank(accessToken)){
                    log.info("未获取到代管理应用token, corpId={}, externalUserId={}", corpApplication.getAuthCorpId(), corpApplication.getPermanentCode());
                    return;
                }
                UseridToOpenuseridResultDTO useridToOpenuseridResultDTO = WwApiUtil.userToOpenuserid(userid_list, accessToken);
                log.info("userid转openuserid接口调用，para={}, result={}",JSONObject.toJSONString(userid_list), JSONObject.toJSONString(useridToOpenuseridResultDTO));
                if(useridToOpenuseridResultDTO != null){
                    List<UseridToOpenuseridResultDTO.OpenUserid> open_userid_list = useridToOpenuseridResultDTO.getOpen_userid_list();
                    if(open_userid_list != null && open_userid_list.size() > 0){
                        for (UseridToOpenuseridResultDTO.OpenUserid openUserid : open_userid_list) {
                            if(StringUtils.isNotBlank(openUserid.getUserid()) && StringUtils.isNotBlank(openUserid.getOpen_userid())){
                                //处理企业机器人信息
                                CorpApplicationDevice corpApplicationDevice = corpApplicationDeviceMapper.selectByDeviceUniqueId(wwDevice.getId());
                                if(corpApplicationDevice == null){
                                    corpApplicationDevice = new CorpApplicationDevice();
                                    corpApplicationDevice.setId(IdWorker.getId());
                                    corpApplicationDevice.setMerId(wwDevice.getMerId());
                                    corpApplicationDevice.setCorpId(wwCorp.getCorpId());
                                    corpApplicationDevice.setCorpName(wwCorp.getName());
                                    corpApplicationDevice.setAuthCorpId(corpApplication.getAuthCorpId());
                                    corpApplicationDevice.setDeviceUniqueId(wwDevice.getId());
                                    corpApplicationDevice.setDeviceId(wwDevice.getDeviceId());
                                    corpApplicationDevice.setUserid(openUserid.getUserid());
                                    corpApplicationDevice.setOpenUserid(openUserid.getOpen_userid());
                                    corpApplicationDevice.setCreateTime(now);
                                    corpApplicationDevice.setUpdateTime(now);
                                    corpApplicationDeviceMapper.insert(corpApplicationDevice);
                                }else{
//                                    corpApplicationDevice.setCorpId(wwCorp.getCorpId());
//                                    corpApplicationDevice.setCorpName(wwCorp.getName());
//                                    corpApplicationDevice.setAuthCorpId(corpApplication.getAuthCorpId());
//                                    corpApplicationDevice.setDeviceUniqueId(wwDevice.getId());
//                                    corpApplicationDevice.setDeviceId(wwDevice.getDeviceId());
//                                    corpApplicationDevice.setUserid(openUserid.getUserid());
//                                    corpApplicationDevice.setOpenUserid(openUserid.getOpen_userid());
//                                    corpApplicationDevice.setCreateTime(now);
//                                    corpApplicationDevice.setUpdateTime(now);
//                                    corpApplicationDeviceMapper.updateById(corpApplicationDevice);
                                }
                            }
                        }
                    }
                }
            }
        } catch (Exception e) {
            log.info(e.getMessage(), e);
        } finally {
            //删除限流key
            redisTemplate.delete(rateLimitKey);
        }
    }

    /**
     * 企业应用推送tikect
     *
     * @param
     * @return null
     * @author liuqi
     * @date 2021/8/13 11:38
     */
    @Async("taskExecutorForQywxCallback")
    public void corpApplicationSuiteTicket(String suiteId, String suiteTicket){
        log.info("进入企业应用推送tikect方法中,suiteId={}, suiteTicket={}", suiteId, suiteTicket);
        if (StringUtils.isBlank(suiteId) || StringUtils.isBlank(suiteTicket)) {
            return;
        }

        redisTemplate.opsForValue().set(RedisCacheKeyEnum.XJ_WW_SITE_SECRET.getKey(), Const.WxworkApplication.templateSecret);
        redisTemplate.opsForValue().set(RedisCacheKeyEnum.XJ_WW_SITE_ID.getKey(), suiteId);
        redisTemplate.opsForValue().set(RedisCacheKeyEnum.XJ_WW_SITE_TICKET.getKey(), suiteTicket);
        //更新代开发应用模板凭证
        WwApiUtil.getSiteToken(suiteId, Const.WxworkApplication.templateSecret, suiteTicket);
    }

    /**
     * 处理企业微信回调
     *
     * @param
     * @return null
     * @author liuqi
     * @date 2021/8/13 11:38
     */
    @Async("taskExecutorForQywxCallback")
    public void corpApplicationCreateAuth(String suiteId, String authCode) {
        log.info("进入企业运用创建授权方法中,suiteId={}, authCode={}", suiteId, authCode);
        if (StringUtils.isBlank(suiteId) || StringUtils.isBlank(authCode)) {
            return;
        }
        String siteToken = WwApiUtil.getSiteTokenV1();
        log.info("获取代开发模板凭证,siteToken={}", siteToken);
        if (StringUtils.isNotBlank(siteToken)) {
            log.info("调用获取应用secret接口");
            WwAppSecretResultDTO appSecret = WwApiUtil.getAppSecret(siteToken, authCode);
            log.info("调用获取应用secret接口返回结果；appSecret={}", JSONObject.toJSONString(appSecret));
            if (appSecret != null) {
                //永久授权码
                String permanent_code = appSecret.getPermanent_code();
                //授权企业信息
                WwAppSecretResultDTO.AuthCorpInfo authCorpInfo = appSecret.getAuth_corp_info();
                if (authCorpInfo != null) {
                    //授权企业id
                    String corpid = authCorpInfo.getCorpid();
                    String corp_name = authCorpInfo.getCorp_name();
                    log.info("解析到企业应用授权企业信息,corpIdThird={}, corp_name={}");
                    if (StringUtils.isNotBlank(corpid) && StringUtils.isNotBlank(corp_name)) {
                        //通过企业名称查询企业应用表
                        CorpApplication corpApplication = corpApplicationMapper.selectByCorpNameSimple(corp_name);
                        if (corpApplication != null) { //查询到该企业，完善企业信息
                            corpApplication.setAuthCorpId(corpid);
                            corpApplication.setPermanentCode(permanent_code);
                            corpApplication.setUpdateTime(DateUtil.getTime());
                            corpApplicationMapper.updateById(corpApplication);

                            //保存缓存
                            String corp_application_auth_corpid_key = String.format(RedisCacheKeyEnum.CORP_APPLICATION_AUTH_CORPID.getKey(), corpApplication.getCorpId());
                            String corp_application_auth_corpid_value = corpApplication.getAuthCorpId() + "::" + corpApplication.getPermanentCode();
                            redisTemplate.opsForValue().set(corp_application_auth_corpid_key, corp_application_auth_corpid_value);

                            //发送钉钉群报警消息

                        }
                    }
                }
            }
        }
    }

    /**
     * 处理企业微信回调
     *
     * @param
     * @return null
     * @author liuqi
     * @date 2021/8/13 11:38
     */
    @Async("taskExecutorForQywxCallback")
    public void corpApplicationResetPermanentCode(String suiteId, String authCode) {
        log.info("进入企业运用重置授权方法中,suiteId={}, authCode={}", suiteId, authCode);
        if (StringUtils.isBlank(suiteId) || StringUtils.isBlank(authCode)) {
            return;
        }
        String siteToken = WwApiUtil.getSiteTokenV1();
        log.info("获取代开发模板凭证,siteToken={}", siteToken);
        if (StringUtils.isNotBlank(siteToken)) {
            log.info("调用获取应用secret接口");
            WwAppSecretResultDTO appSecret = WwApiUtil.getAppSecret(siteToken, authCode);
            log.info("调用获取应用secret接口返回结果；appSecret={}", JSONObject.toJSONString(appSecret));
            if (appSecret != null) {
                //永久授权码
                String permanent_code = appSecret.getPermanent_code();
                //授权企业信息
                WwAppSecretResultDTO.CorpInfo corpInfo = appSecret.getDealer_corp_info();
                if (corpInfo != null) {
                    //授权企业id
                    String corpid = corpInfo.getCorpid();
                    String corp_name = corpInfo.getCorp_name();
                    log.info("解析到企业应用授权企业信息,corpIdThird={}, corp_name={}");
                    if (StringUtils.isNotBlank(corpid) && StringUtils.isNotBlank(corp_name)) {
                        //通过企业名称查询企业应用表
                        CorpApplication corpApplication = corpApplicationMapper.selectByCorpNameSimple(corp_name);
                        if (corpApplication != null) { //查询到该企业，完善企业信息
                            corpApplication.setAuthCorpId(corpid);
                            corpApplication.setPermanentCode(permanent_code);
                            corpApplication.setUpdateTime(DateUtil.getTime());
                            corpApplicationMapper.updateById(corpApplication);
                        }
                    }
                }
            }
        }
    }

    /**
     * 企业应用取消授权
     *
     * @param
     * @return null
     * @author liuqi
     * @date 2021/8/13 11:38
     */
    @Async("taskExecutorForQywxCallback")
    public void corpApplicationCancelAuth(String suiteId, String authCorpId) {
        log.info("进入企业运用取消授权方法中,suiteId={}, authCode={}", suiteId, authCorpId);
        if (StringUtils.isNotBlank(suiteId) && StringUtils.isNotBlank(authCorpId)) {
            CorpApplication corpApplication = corpApplicationMapper.selectByAuthCorpId(authCorpId);
            if (corpApplication != null) { //查询到该企业，取消该企业的授权信息
                corpApplication.setAuthCorpId(null);
                corpApplication.setPermanentCode(null);
                corpApplication.setUpdateTime(DateUtil.getTime());
                corpApplicationMapper.updateById(corpApplication);

                //保存缓存
                String corp_application_auth_corpid_key = String.format(RedisCacheKeyEnum.CORP_APPLICATION_AUTH_CORPID.getKey(), corpApplication.getCorpId());
                redisTemplate.delete(corp_application_auth_corpid_key);

                //清除token
                String xjWwAppTokenKey = String.format(RedisCacheKeyEnum.XJ_WW_APP_TOKEN.getKey(), authCorpId);
                redisTemplate.delete(xjWwAppTokenKey);

            }
        }
    }


    /**
     * 处理企业微信会员信息回调
     *
     * @param
     * @return null
     * @author liuqi
     * @date 2021/8/13 11:38
     */
    @Async("taskExecutorForQywxCallback")
    public void handerUserCallback(String corpId, String externalUserId) {
        log.info("进入企业运用取消授权方法中,corpId={}, externalUserId={}", corpId, externalUserId);
        if (StringUtils.isNotBlank(corpId) && StringUtils.isNotBlank(externalUserId)) {

            //查询企业是否存在
            CorpApplication corpApplication = corpApplicationMapper.selectByAuthCorpId(corpId);
            if(corpApplication == null){
                log.info("该企业还未授权,corpId={}, externalUserId={}", corpId, externalUserId);
                return;
            }

            String accessToken = WwApiUtil.getAppAccessToken(corpId, corpApplication.getPermanentCode());
            if(StringUtils.isBlank(accessToken)){
                log.info("未获取到代管理应用token, corpId={}, externalUserId={}", corpId, externalUserId);
                return;
            }

            //获取外部会员详情
            WwCustomerResultDTO customerDetail = WwApiUtil.getCustomerDetail(accessToken, externalUserId, null);
            if (customerDetail != null) {
                //直接处理
                qywxCallbackService.handerWwCustomerResultDTO(corpApplication.getMerId(), corpId, customerDetail);
                Integer next_cursor = customerDetail.getNext_cursor();
            }else{
                log.info("未获取到会员外部账号详情");
            }

        }
    }


    /**
     * 处理企业微信会员信息回调
     *
     * @param
     * @return null
     * @author liuqi
     * @date 2021/8/13 11:38
     */
    @Async("taskExecutorForQywxCallback")
    public void handerUserCallbackByWxwork(String corpId, String externalUserId){
        //查询企业是否存在
        CorpApplication corpApplication = corpApplicationMapper.selectByAuthCorpId(corpId);
        if(corpApplication == null){
            log.info("该企业还未授权,corpId={}, externalUserId={}", corpId, externalUserId);
            return;
        }

        //直接处理
        qywxCallbackService.handerQywxCallback(corpApplication.getMerId(), "dcl", externalUserId);

    }

    /**
     * 查询企业
     *
     * @param
     * @return null
     * @author liuqi
     * @date 2021/8/13 11:38
     */
    public CorpApplication selectByCorpId(String corpId){
        return  corpApplicationMapper.selectByCorpId(corpId);
    }

}
